import math
import geopandas as gpd
import pandas as pd
from shapely.geometry import MultiPolygon
import folium
from folium import Choropleth, Marker
from folium.plugins import HeatMap, MarkerCluster
# from learntools.core import binder
# binder.bind(globals())
# from learntools.geospatial.ex5 import *This notebook is an exercise in the Geospatial Analysis course. You can reference the tutorial at this link.
소개
당신은 위기 대응 팀의 일원이며, 뉴욕 시에서 발생한 교통사고에 대한 병원들의 대응 상황을 파악하고자 합니다.

아래의 코드 셀을 실행하여 모든 설정을 마치세요.
지도를 시각화하기 위해 embed_map() 함수를 사용할 것입니다.
def embed_map(m, file_name):
from IPython.display import IFrame
m.save(file_name)
return IFrame(file_name, width='100%', height='500px')연습문제
1) 충돌 데이터 시각화하기
아래의 코드 셀을 실행하여 2013년부터 2018년까지 주요 자동차 충돌을 추적하는 GeoDataFrame인 collisions을 불러오세요.
collisions = gpd.read_file("archive_5/NYPD_Motor_Vehicle_Collisions/NYPD_Motor_Vehicle_Collisions/NYPD_Motor_Vehicle_Collisions.shp")
collisions.head()| DATE | TIME | BOROUGH | ZIP CODE | LATITUDE | LONGITUDE | LOCATION | ON STREET | CROSS STRE | OFF STREET | ... | CONTRIBU_2 | CONTRIBU_3 | CONTRIBU_4 | UNIQUE KEY | VEHICLE TY | VEHICLE _1 | VEHICLE _2 | VEHICLE _3 | VEHICLE _4 | geometry | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 07/30/2019 | 0:00 | BRONX | 10464 | 40.841100 | -73.784960 | (40.8411, -73.78496) | NaN | NaN | 121 PILOT STREET | ... | Unspecified | NaN | NaN | 4180045 | Sedan | Station Wagon/Sport Utility Vehicle | Station Wagon/Sport Utility Vehicle | NaN | NaN | POINT (1043750.211 245785.815) |
| 1 | 07/30/2019 | 0:10 | QUEENS | 11423 | 40.710827 | -73.770660 | (40.710827, -73.77066) | JAMAICA AVENUE | 188 STREET | NaN | ... | NaN | NaN | NaN | 4180007 | Sedan | Sedan | NaN | NaN | NaN | POINT (1047831.185 198333.171) |
| 2 | 07/30/2019 | 0:25 | NaN | NaN | 40.880318 | -73.841286 | (40.880318, -73.841286) | BOSTON ROAD | NaN | NaN | ... | NaN | NaN | NaN | 4179575 | Sedan | Station Wagon/Sport Utility Vehicle | NaN | NaN | NaN | POINT (1028139.293 260041.178) |
| 3 | 07/30/2019 | 0:35 | MANHATTAN | 10036 | 40.756744 | -73.984590 | (40.756744, -73.98459) | NaN | NaN | 155 WEST 44 STREET | ... | NaN | NaN | NaN | 4179544 | Box Truck | Station Wagon/Sport Utility Vehicle | NaN | NaN | NaN | POINT (988519.261 214979.320) |
| 4 | 07/30/2019 | 10:00 | BROOKLYN | 11223 | 40.600090 | -73.965910 | (40.60009, -73.96591) | AVENUE T | OCEAN PARKWAY | NaN | ... | NaN | NaN | NaN | 4180660 | Station Wagon/Sport Utility Vehicle | Bike | NaN | NaN | NaN | POINT (993716.669 157907.212) |
5 rows × 30 columns
“LATITUDE”와 “LONGITUDE” 열을 사용하여 충돌 데이터를 시각화하는 인터랙티브 맵을 생성하세요. 어떤 종류의 맵이 가장 효과적인지 생각하시나요?
m_1 = folium.Map(location=[40.7, -74], zoom_start=11)
# Your code here: Visualize the collision data
HeatMap(data=collisions[["LATITUDE","LONGITUDE"]],redius=9).add_to(m_1)
m_1
# Uncomment to see a hint
#q_1.hint()
# Show the map
#embed_map(m_1, "q_1.html")# Get credit for your work after you have created a map
#q_1.check()
# Uncomment to see our solution (your code may look different!)
#q_1.solution()2) 병원 커버리지 이해하기
다음의 코드 셀을 실행하여 병원 데이터를 불러오세요.
hospitals = gpd.read_file("archive_5/nyu_2451_34494/nyu_2451_34494/nyu_2451_34494.shp")
hospitals.head()| id | name | address | zip | factype | facname | capacity | capname | bcode | xcoord | ycoord | latitude | longitude | geometry | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 317000001H1178 | BRONX-LEBANON HOSPITAL CENTER - CONCOURSE DIVI... | 1650 Grand Concourse | 10457 | 3102 | Hospital | 415 | Beds | 36005 | 1008872.0 | 246596.0 | 40.843490 | -73.911010 | POINT (1008872.000 246596.000) |
| 1 | 317000001H1164 | BRONX-LEBANON HOSPITAL CENTER - FULTON DIVISION | 1276 Fulton Ave | 10456 | 3102 | Hospital | 164 | Beds | 36005 | 1011044.0 | 242204.0 | 40.831429 | -73.903178 | POINT (1011044.000 242204.000) |
| 2 | 317000011H1175 | CALVARY HOSPITAL INC | 1740-70 Eastchester Rd | 10461 | 3102 | Hospital | 225 | Beds | 36005 | 1027505.0 | 248287.0 | 40.848060 | -73.843656 | POINT (1027505.000 248287.000) |
| 3 | 317000002H1165 | JACOBI MEDICAL CENTER | 1400 Pelham Pkwy | 10461 | 3102 | Hospital | 457 | Beds | 36005 | 1027042.0 | 251065.0 | 40.855687 | -73.845311 | POINT (1027042.000 251065.000) |
| 4 | 317000008H1172 | LINCOLN MEDICAL & MENTAL HEALTH CENTER | 234 E 149 St | 10451 | 3102 | Hospital | 362 | Beds | 36005 | 1005154.0 | 236853.0 | 40.816758 | -73.924478 | POINT (1005154.000 236853.000) |
“latitude”와 “longitude” 열을 사용하여 병원의 위치를 시각화하세요.
m_2 = folium.Map(location=[40.7, -74], zoom_start=11)
# Your code here: Visualize the hospital locations
for idx, row in hospitals.iterrows():
Marker([row['latitude'],row['longitude']],popup=row['name'], icon=folium.Icon(color='red')).add_to(m_2)
m_2
# Uncomment to see a hint
#q_2.hint()
# Show the map
#embed_map(m_2, "q_2.html")# Get credit for your work after you have created a map
#q_2.check()
# Uncomment to see our solution (your code may look different!)
#q_2.solution()3) 가장 가까운 병원으로부터 10킬로미터 이상 떨어진 시점은 언제였나요?
가장 가까운 병원으로부터 10킬로미터 이상 떨어진 위치에서 발생한 충돌을 가진 collisions의 모든 행을 포함하는 DataFrame outside_range을 생성하세요.
참고로, hospitals와 collisions 모두 좌표 참조 시스템으로 EPSG 2263을 사용하며, EPSG 2263은 미터 단위입니다.
# Your code here
h = gpd.GeoDataFrame(geometry=hospitals.geometry).buffer(10000)
u= h.geometry.unary_union
outside_range = collisions.loc[~collisions["geometry"].apply(lambda X: u.contains(X))]
outside_range
# Check your answer
#q_3.check()| DATE | TIME | BOROUGH | ZIP CODE | LATITUDE | LONGITUDE | LOCATION | ON STREET | CROSS STRE | OFF STREET | ... | CONTRIBU_2 | CONTRIBU_3 | CONTRIBU_4 | UNIQUE KEY | VEHICLE TY | VEHICLE _1 | VEHICLE _2 | VEHICLE _3 | VEHICLE _4 | geometry | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 07/30/2019 | 0:00 | BRONX | 10464 | 40.841100 | -73.784960 | (40.8411, -73.78496) | NaN | NaN | 121 PILOT STREET | ... | Unspecified | NaN | NaN | 4180045 | Sedan | Station Wagon/Sport Utility Vehicle | Station Wagon/Sport Utility Vehicle | NaN | NaN | POINT (-73.785 40.841) |
| 1 | 07/30/2019 | 0:10 | QUEENS | 11423 | 40.710827 | -73.770660 | (40.710827, -73.77066) | JAMAICA AVENUE | 188 STREET | NaN | ... | NaN | NaN | NaN | 4180007 | Sedan | Sedan | NaN | NaN | NaN | POINT (-73.771 40.711) |
| 2 | 07/30/2019 | 0:25 | NaN | NaN | 40.880318 | -73.841286 | (40.880318, -73.841286) | BOSTON ROAD | NaN | NaN | ... | NaN | NaN | NaN | 4179575 | Sedan | Station Wagon/Sport Utility Vehicle | NaN | NaN | NaN | POINT (-73.841 40.880) |
| 3 | 07/30/2019 | 0:35 | MANHATTAN | 10036 | 40.756744 | -73.984590 | (40.756744, -73.98459) | NaN | NaN | 155 WEST 44 STREET | ... | NaN | NaN | NaN | 4179544 | Box Truck | Station Wagon/Sport Utility Vehicle | NaN | NaN | NaN | POINT (-73.985 40.757) |
| 4 | 07/30/2019 | 10:00 | BROOKLYN | 11223 | 40.600090 | -73.965910 | (40.60009, -73.96591) | AVENUE T | OCEAN PARKWAY | NaN | ... | NaN | NaN | NaN | 4180660 | Station Wagon/Sport Utility Vehicle | Bike | NaN | NaN | NaN | POINT (-73.966 40.600) |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 261900 | 07/01/2012 | 8:27 | NaN | NaN | 40.708797 | -73.727620 | (40.7087971, -73.72762) | NaN | NaN | NaN | ... | NaN | NaN | NaN | 3016724 | PASSENGER VEHICLE | NaN | NaN | NaN | NaN | POINT (-73.728 40.709) |
| 261901 | 07/01/2012 | 8:34 | BROOKLYN | 11213 | 40.668798 | -73.931120 | (40.6687978, -73.9311201) | EASTERN PARKWAY | UTICA AVENUE | NaN | ... | NaN | NaN | NaN | 172551 | PASSENGER VEHICLE | VAN | NaN | NaN | NaN | POINT (-73.931 40.669) |
| 261902 | 07/01/2012 | 8:37 | QUEENS | 11435 | 40.694545 | -73.802112 | (40.6945453, -73.802112) | SOUTH ROAD | SUTPHIN BOULEVARD | NaN | ... | NaN | NaN | NaN | 208724 | UNKNOWN | NaN | NaN | NaN | NaN | POINT (-73.802 40.695) |
| 261903 | 07/01/2012 | 9:00 | MANHATTAN | 10022 | 40.757859 | -73.975592 | (40.7578587, -73.975592) | EAST 50 STREET | MADISON AVENUE | NaN | ... | NaN | NaN | NaN | 37634 | TAXI | NaN | NaN | NaN | NaN | POINT (-73.976 40.758) |
| 261904 | 07/01/2012 | 9:30 | BROOKLYN | 11207 | 40.678163 | -73.897477 | (40.6781627, -73.8974769) | JAMAICA AVENUE | PENNSYLVANIA AVENUE | NaN | ... | NaN | NaN | NaN | 163374 | SPORT UTILITY / STATION WAGON | PASSENGER VEHICLE | NaN | NaN | NaN | POINT (-73.897 40.678) |
261905 rows × 30 columns
# Lines below will give you a hint or solution code
#q_3.hint()
#q_3.solution()다음 코드 셀은 가장 가까운 병원으로부터 10킬로미터 이상 떨어진 위치에서 발생한 충돌의 비율을 계산합니다.
percentage = round(100*len(outside_range)/len(collisions), 2)
print("Percentage of collisions more than 10 km away from the closest hospital: {}%".format(percentage))Percentage of collisions more than 10 km away from the closest hospital: 100.0%
4) 추천 시스템 만들기
먼 거리에서 충돌이 발생할 경우, 부상자가 가장 가까운 이용 가능한 병원으로 이송되는 것이 더욱 중요해집니다.
이를 고려하여 다음과 같은 추천 시스템을 만들기로 결정하였습니다: - 충돌 위치 (EPSG 2263 좌표계)를 입력으로 받습니다. - 가장 가까운 병원을 찾아냅니다 (거리 계산은 EPSG 2263에서 이루어집니다). - 가장 가까운 병원의 이름을 반환합니다.
def best_hospital(collision_location):
distances = hospitals.geometry.distance(collision_location)
closest_hospital_idx = distances.idxmin()
name = hospitals.loc[closest_hospital_idx, "name"]
return name
# Test your function: this should suggest CALVARY HOSPITAL INC
print(best_hospital(outside_range.geometry.iloc[0]))
# Check your answer
#q_4.check()STATEN ISLAND UNIVERSITY HOSP-SOUTH
# Lines below will give you a hint or solution code
#q_4.hint()
#q_4.solution()5) 가장 많은 수요를 받고 있는 병원은 어디인가요?
outside_range DataFrame에서만 충돌을 고려했을 때, 가장 추천되는 병원은 어느 병원인가요?
답변은 4)에서 생성한 함수로 반환되는 병원의 이름과 정확히 일치하는 Python 문자열이어야 합니다.
# Your code here
hospital_demand = outside_range["BOROUGH"].value_counts()
most_demand_hospital = best_hospital(outside_range.geometry.iloc[0])
# Check your answer
#q_5.check()# Lines below will give you a hint or solution code
#q_5.hint()
#q_5.solution()6) 도시는 어디에 새로운 병원을 건설해야 할까요?
다음 코드 셀을 실행하여 (수정하지 않고) 병원 위치와 가장 가까운 병원으로부터 10킬로미터 이상 떨어진 위치에서 발생한 충돌을 시각화하세요.
m_6 = folium.Map(location=[40.7, -74], zoom_start=11)
coverage = gpd.GeoDataFrame(geometry=hospitals.geometry).buffer(10000)
folium.GeoJson(coverage.geometry.to_crs(epsg=4326)).add_to(m_6)
HeatMap(data=outside_range[['LATITUDE', 'LONGITUDE']], radius=9).add_to(m_6)
folium.LatLngPopup().add_to(m_6)
m_6
#embed_map(m_6, 'm_6.html')맵에서 아무 곳이나 클릭하면 해당 위치의 위도와 경도가 표시되는 팝업이 표시됩니다.
뉴욕 시는 두 개의 새로운 병원 위치 결정을 위해 여러분에게 도움을 청합니다. 특히, 3) 단계에서 계산된 비율을 10% 미만으로 줄일 수 있는 위치를 찾는 데 도움이 필요합니다. 맵을 사용하여 (구역 법률이나 건물 건설을 위해 제거해야 할 잠재적인 건물에 대해 걱정하지 않고) 도시가 이 목표를 달성하는 데 도움이 되는 두 곳의 위치를 식별할 수 있을까요?
병원 1의 제안된 위도와 경도를 각각 lat_1과 long_1에 입력하세요. (병원 2도 동일하게 입력하세요.)
그런 다음 셀의 나머지 부분을 그대로 실행하여 새로운 병원의 효과를 확인하세요. 답변은 새로운 병원을 통해 비율을 10% 미만으로 낮추는 경우 정답으로 표시됩니다.
# Your answer here: proposed location of hospital 1
lat_1 = 40.7443
long_1 = -73.9146
# Your answer here: proposed location of hospital 2
lat_2 = 40.7443
long_2 = -73.9146
# Do not modify the code below this line
try:
new_df = pd.DataFrame(
{'Latitude': [lat_1, lat_2],
'Longitude': [long_1, long_2]})
new_gdf = gpd.GeoDataFrame(new_df, geometry=gpd.points_from_xy(new_df.Longitude, new_df.Latitude))
new_gdf.crs = {'init' :'epsg:4326'}
new_gdf = new_gdf.to_crs(epsg=2263)
# get new percentage
new_coverage = gpd.GeoDataFrame(geometry=new_gdf.geometry).buffer(10000)
new_my_union = new_coverage.geometry.unary_union
new_outside_range = outside_range.loc[~outside_range["geometry"].apply(lambda x: new_my_union.contains(x))]
new_percentage = round(100*len(new_outside_range)/len(collisions), 2)
print("(NEW) Percentage of collisions more than 10 km away from the closest hospital: {}%".format(new_percentage))
# make the map
m = folium.Map(location=[40.7, -74], zoom_start=11)
folium.GeoJson(coverage.geometry.to_crs(epsg=4326)).add_to(m)
folium.GeoJson(new_coverage.geometry.to_crs(epsg=4326)).add_to(m)
for idx, row in new_gdf.iterrows():
Marker([row['Latitude'], row['Longitude']]).add_to(m)
HeatMap(data=new_outside_range[['LATITUDE', 'LONGITUDE']], radius=9).add_to(m)
folium.LatLngPopup().add_to(m)
display(m)
except:
0c:\Users\leegabin\anaconda3\lib\site-packages\pyproj\crs\crs.py:141: FutureWarning: '+init=<authority>:<code>' syntax is deprecated. '<authority>:<code>' is the preferred initialization method. When making the change, be mindful of axis order changes: https://pyproj4.github.io/pyproj/stable/gotchas.html#axis-order-changes-in-proj-6
in_crs_string = _prepare_from_proj_string(in_crs_string)
(NEW) Percentage of collisions more than 10 km away from the closest hospital: 100.0%
# Uncomment to see one potential answer
#q_6.solution()Congratulations!
You have just completed the Geospatial Analysis micro-course! Great job!
Have questions or comments? Visit the course discussion forum to chat with other learners.